﻿using CoreModule;
using CoreModule.Storages;
using Microsoft.EntityFrameworkCore;
using Microsoft.Win32;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using Prism.Mvvm;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
namespace IdResourceModule.ViewModels
{
    /// <summary>
    /// 
    /// </summary>
    public class MeasurementListViewModel : BindableBase, 
        IRegionMemberLifetime,
        INavigationAware
    {
        public string Title { get; set; } = string.Empty;
        public bool KeepAlive => false;
        public string PatientName { get; set; } = string.Empty;
        /// <summary>
        /// 
        /// </summary>
        public string IdCard { get; set; } = string.Empty;
        /// <summary>
        /// 
        /// </summary>
        public string SocialCard { get; set; } = string.Empty;
        /// <summary>
        /// 
        /// </summary>
        public int TodayNewNum { get; set; } = 0;
        /// <summary>
        /// 
        /// </summary>
        public int TotalNum { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public int NeedAttentionNum { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string WdCode { get; set; } = "";
         
        /// <summary>
        /// 
        /// </summary>
        public DateTime? BeingMeasurementTime { get; set; } = DateTime.Now.AddDays(-7);
        /// <summary>
        /// 
        /// </summary>
        public DateTime? EndMeasurementTime { get; set; } = DateTime.Now;
        /// <summary>
        /// 
        /// </summary>
        public List<KeyValuePair<string, PressureStatus>> SbpStatusItemsSource { get; set; } = IdResourceModule.PressureStatusExtension.SBPPressureStatusItemsSource;
        /// <summary>
        /// 
        /// </summary>
        public List<KeyValuePair<string, PressureStatus>> DbpStatusItemsSource { get; set; } = IdResourceModule.PressureStatusExtension.DBPPressureStatusItemsSource;
        /// <summary>
        /// 
        /// </summary>
        public PressureStatus SbpStatus { get; set; } = PressureStatus.None;
        /// <summary>
        /// 
        /// </summary>
        public PressureStatus DbpStatus { get; set; } = PressureStatus.None;
        public List<KeyValuePair<string, PressureLevel>> BpLevelItemsSource { get; set; } = IdResourceModule.PressureLevelExtension.PressureLevelItemsSource;
        /// <summary>
        /// 
        /// </summary>
        public PressureLevel BpLevel { get; set; } = PressureLevel.None;
        /// <summary>
        /// 
        /// </summary>
        public int EntityTotalCount { get; set; } = 0;
   
        public int DataCountPerPage { get; set; } = 10;
        /// <summary>
        /// 
        /// </summary>
        public int MaxPageCount { get; set; }
         
        /// <summary>
        /// 
        /// </summary>
        public ICommand QueryCommand   => new Prism.Commands.DelegateCommand(Query);
        public ICommand ResetCommand => new Prism.Commands.DelegateCommand(Reset);
        public ICommand ExportCommand => new Prism.Commands.DelegateCommand(Export);
        public ICommand PrintCommand => new Prism.Commands.DelegateCommand(Print);
        public ICommand PageUpdatedCommand => new Prism.Commands.DelegateCommand<object>(PageUpdated);
       
        DbStorage DbStorage { get; set; }
        INotifier Notifier { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public MeasurementListViewModel(IRegionManager regionManager, DbStorage dbStorage,INotifier notifier)
        {
            RegionManager = regionManager;
            DbStorage = dbStorage;
            Notifier = notifier;
            this.UpdateStatistic();
             
            this.Query();
        }
        /// <summary>
        /// 
        /// </summary>
        public void Print()
        {
         
        }
        /// <summary>
        /// 
        /// </summary>
        public  void Export()
        {

            var String_Blood_Pressure_Measurement_Records = WPFLocalizeExtension.Engine.LocalizeDictionary.Instance.GetLocalizedObject("String_Blood_Pressure_Measurement_Records", null, null) + "";


            var entities = CreateQueryable().ToList();
           
           SaveFileDialog dialog = new SaveFileDialog()
            {
                Filter = "Excel(*.xlsx *.xls)|*.xlsx;*.xls",
                FileName = $"{String_Blood_Pressure_Measurement_Records} {DateTime.Now.ToString("yyyyMMddHHmmss")}"
            };
            string filePath = "";
            if (dialog.ShowDialog().GetValueOrDefault())
            {
                filePath = dialog.FileName;
            }
            var sheetRowCount = 20000;
            if (!string.IsNullOrEmpty(filePath))
            {
             
                XSSFWorkbook book = new XSSFWorkbook();
                for (int i = 0; i < entities.Count; i+= sheetRowCount)
                {
                  CreateSheetForRecord(book, entities.Skip(i).Take(sheetRowCount).ToList());
                }
                  
                using (System.IO.FileStream bookStream = new System.IO.FileStream(filePath, System.IO.FileMode.Create))
                {
                    book.Write(bookStream);
                    bookStream.Close();
                }
                try
                {
                    //System.Diagnostics.Process.Start(dialog.FileName.Replace(dialog.SafeFileName, ""));
                    string pathToFolder = dialog.FileName.Replace(dialog.SafeFileName, "");
                    var psi = new System.Diagnostics.ProcessStartInfo() { FileName = pathToFolder, UseShellExecute = true };
                    System.Diagnostics.Process.Start(psi);
                }
                catch (Exception)
                {
                  
                }
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        private ISheet CreateSheetForRecord(XSSFWorkbook book ,  List<MeasurementResultInfo> entities)
        {
            
            var String_Customer_Name =  WPFLocalizeExtension.Engine.LocalizeDictionary.Instance.GetLocalizedObject("String_Customer_Name", null, null) + "";
            var String_User_ID = WPFLocalizeExtension.Engine.LocalizeDictionary.Instance.GetLocalizedObject("String_User_ID", null, null) + "";
            var String_Medical_Insurance_Card_Number = WPFLocalizeExtension.Engine.LocalizeDictionary.Instance.GetLocalizedObject("String_Medical_Insurance_Card_Number", null, null) + "";
            var String_ID_Number = WPFLocalizeExtension.Engine.LocalizeDictionary.Instance.GetLocalizedObject("String_ID_Number", null, null) + "";
            var String_Measurement_Time = WPFLocalizeExtension.Engine.LocalizeDictionary.Instance.GetLocalizedObject("String_Measurement_Time", null, null) + "";

            var String_Systolic_Pressure = WPFLocalizeExtension.Engine.LocalizeDictionary.Instance.GetLocalizedObject("String_Systolic_Pressure", null, null) + "";
            var String_Diastolic_Pressure = WPFLocalizeExtension.Engine.LocalizeDictionary.Instance.GetLocalizedObject("String_Diastolic_Pressure", null, null) + "";

            var String_Pulse = WPFLocalizeExtension.Engine.LocalizeDictionary.Instance.GetLocalizedObject("String_Pulse", null, null) + "";

            var String_Minute = WPFLocalizeExtension.Engine.LocalizeDictionary.Instance.GetLocalizedObject("String_Minute", null, null) + "";

            var String_SBP_Status = WPFLocalizeExtension.Engine.LocalizeDictionary.Instance.GetLocalizedObject("String_SBP_Status", null, null) + "";
            var String_DBP_Status = WPFLocalizeExtension.Engine.LocalizeDictionary.Instance.GetLocalizedObject("String_DBP_Status", null, null) + "";

            var String_Blood_Pressure_Grade = WPFLocalizeExtension.Engine.LocalizeDictionary.Instance.GetLocalizedObject("String_Blood_Pressure_Grade", null, null) + "";

            var String_Remarks = WPFLocalizeExtension.Engine.LocalizeDictionary.Instance.GetLocalizedObject("String_Remarks", null, null) + "";



            ISheet sheet = book.CreateSheet();
            IRow rowTitle = sheet.CreateRow(0);
            List<string> names = new List<string>();
            names.Add(String_Customer_Name);
            names.Add(String_User_ID);
            names.Add(String_Medical_Insurance_Card_Number);
            names.Add(String_ID_Number);
            names.Add(String_Measurement_Time);
            names.Add(String_Systolic_Pressure+"(mmHg)");
            names.Add(String_Diastolic_Pressure+"(mmHg)");
            names.Add(String_Pulse+"(kali/"+ String_Minute + ")");
            names.Add(String_SBP_Status);
            names.Add(String_DBP_Status);
            names.Add(String_Blood_Pressure_Grade);
            names.Add(String_Remarks);
            for (int i = 0; i < names.Count; i++)
            {
                rowTitle.CreateCell(i).SetCellValue(names[i]);
            }
            sheet.DefaultColumnWidth = 10;
            sheet.SetColumnWidth(1, 25 * 256);
            sheet.SetColumnWidth(2, 25 * 256);
            sheet.SetColumnWidth(3, 25 * 256);
            sheet.SetColumnWidth(4, 25 * 256);
            var index = 1;
            foreach (var entity in entities)
            {
                NPOI.SS.UserModel.IRow itRow = sheet.CreateRow(index);
                List<string> cols = new List<string>();
                cols.Add(entity.PatientInfo.PatientName);
                cols.Add(entity.PatientInfo.WdCode);
                cols.Add(entity.PatientInfo.SocialCard);
                cols.Add(entity.PatientInfo.IdCard);
                cols.Add(entity.MeasurementTime.ToString("yyyy-MM-dd HH:mm:ss"));
                cols.Add(entity.SBP.ToString());
                cols.Add(entity.DBP.ToString());
                cols.Add(entity.PulseRate.ToString());
                cols.Add(entity.SbpStatus.GetDescription());
                cols.Add(entity.DbpStatus.GetDescription());
                cols.Add(entity.BpLevel.GetDescription());
                cols.Add(entity.Remark);
                for (int j = 0; j < cols.Count; j++)
                {
                    itRow.CreateCell(j).SetCellValue(cols[j]);
                }
                index = index + 1;
            }
            return sheet;
     
        }
        /// <summary>
        /// 
        /// </summary>
        public  void Reset()
        {
            this.PatientName = string.Empty;
            this.IdCard = string.Empty;
            this.SocialCard = string.Empty;
            this.WdCode = string.Empty;
            this.BeingMeasurementTime = DateTime.Now.AddDays(-7);
            this.EndMeasurementTime = DateTime.Now;
              
            this.DbpStatus = PressureStatus.None;
            this.SbpStatus = PressureStatus.None;
            this.BpLevel = PressureLevel.None;
            this.RaisePropertyChanged(nameof(this.PatientName));
            this.RaisePropertyChanged(nameof(this.IdCard));
            this.RaisePropertyChanged(nameof(this.SocialCard));
            this.RaisePropertyChanged(nameof(this.WdCode));
            this.RaisePropertyChanged(nameof(this.BeingMeasurementTime));
            this.RaisePropertyChanged(nameof(this.EndMeasurementTime));
            this.RaisePropertyChanged(nameof(this.DbpStatus));
            this.RaisePropertyChanged(nameof(this.SbpStatus));
            this.RaisePropertyChanged(nameof(this.BpLevel));
        }
        /// <summary>
        /// 
        /// </summary>
        HandyControl.Controls.Pagination Pagination { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public void ResetPaginationPageIndex()
        {
            if (Pagination == null)
            {
                return;
            }
            Pagination.PageIndex = 1;
        }
        /// <summary>
        /// 
        /// </summary>
        public  async void PageUpdated(object sender)
        {
           
           var paginationArgs= sender as HandyControl.Data.FunctionEventArgs<int>;
            var pageIndex = paginationArgs.Info;
            Pagination = paginationArgs.OriginalSource as HandyControl.Controls.Pagination;
           await   Query(pageIndex);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public IQueryable<CoreModule.MeasurementResultInfo> CreateQueryable()
        {
            var beginTime = this.BeingMeasurementTime.HasValue ? new DateTime(this.BeingMeasurementTime.Value.Year,
           this.BeingMeasurementTime.Value.Month, this.BeingMeasurementTime.Value.Day) : new DateTime(2000, 10, 10);
            var endTime = this.EndMeasurementTime.HasValue ? new DateTime(this.EndMeasurementTime.Value.Year
                , this.EndMeasurementTime.Value.Month, this.EndMeasurementTime.Value.Day).AddDays(1) : new DateTime(3000, 10, 10);
            return DbStorage.MeasurementResultInfos
                     .Include(item => item.PatientInfo)
                    .Where(item => !string.IsNullOrEmpty(this.PatientName) ? item.PatientInfo.PatientName.Contains( this.PatientName ): true)
                    .Where(item => !string.IsNullOrEmpty(this.WdCode) ? item.PatientInfo.WdCode.Contains(this.WdCode) : true)
                    .Where(item => !string.IsNullOrEmpty(this.SocialCard) ? item.PatientInfo.SocialCard.Contains(this.SocialCard) : true)
                    .Where(item => !string.IsNullOrEmpty(this.IdCard) ? item.PatientInfo.IdCard.Contains(this.IdCard) : true)
                    .Where(item => BeingMeasurementTime.HasValue ? item.MeasurementTime >= beginTime : true)
                    .Where(item => EndMeasurementTime.HasValue ? item.MeasurementTime <= endTime : true)
                    .Where(item => SbpStatus != PressureStatus.None ? item.SbpStatus == SbpStatus : true)
                    .Where(item => DbpStatus != PressureStatus.None ? item.DbpStatus == DbpStatus : true)
                    .Where(item => BpLevel != PressureLevel.None ? item.BpLevel == BpLevel : true);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="pageIndex"></param>
        public async Task Query(int pageIndex)
        {
   
            MeasurementResultInfos.Clear();
              
            try
            {
                EntityTotalCount = CreateQueryable().Count();
                this.RaisePropertyChanged(nameof(EntityTotalCount));
                MaxPageCount = (int)Math.Ceiling(EntityTotalCount * 1.0 / this.DataCountPerPage);
                this.RaisePropertyChanged(nameof(MaxPageCount));
                var items = await CreateQueryable()
                    .OrderByDescending(item => item.CreateTime)
                    .Skip((pageIndex - 1) * this.DataCountPerPage)
                    .Take(this.DataCountPerPage)
                    .ToListAsync();
                MeasurementResultInfos.AddRange(items);
            }
            catch (Exception ex)
            {
               // Notifier.ShowWarning(ex.Message);
            }
         
        }
        /// <summary>
        /// 
        /// </summary>
        public  async void Query()
        {
          await  Query(1);
        }
          
        /// <summary>
        /// 
        /// </summary>
        public ObservableCollection<MeasurementResultInfo> MeasurementResultInfos { get; set; } = new ObservableCollection<MeasurementResultInfo>();
        IRegionManager RegionManager { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public void UpdateStatistic()
        {
            var now = DateTime.Now;
            var beginTime = new DateTime(now.Year, now.Month, now.Day);
            var endTime = new DateTime(now.Year, now.Month, now.Day).AddDays(1);
            try
            {
                this.TodayNewNum = this.DbStorage.MeasurementResultInfos
                    .Count(item => item.CreateTime >= beginTime && item.CreateTime <= endTime);
                this.TotalNum = this.DbStorage.MeasurementResultInfos
                   .Count();
                this.NeedAttentionNum = DbStorage
                    .MeasurementResultInfos
                    .Count(it => it.DbpStatus != PressureStatus.Normal || it.SbpStatus != PressureStatus.Normal);
                this.RaisePropertyChanged(nameof(TodayNewNum));
                this.RaisePropertyChanged(nameof(TotalNum));
                this.RaisePropertyChanged(nameof(NeedAttentionNum));
            }
            catch (Exception ex)
            {
             //   Notifier.ShowWarning(ex.Message);
            }
        }
     
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="navigationContext"></param>
        public void OnNavigatedTo(NavigationContext navigationContext)
        {
             
        }
        public bool IsNavigationTarget(NavigationContext navigationContext)
        {
            return true;
        }
        public void OnNavigatedFrom(NavigationContext navigationContext)
        {
             
        }
    }
}
